package artibella.media.video 
{
	import artibella.media.events.MediaEvent;
	import artibella.IDisposable;
	import artibella.loaders.ILoaderAgent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.NetStatusEvent;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.net.ObjectEncoding;
	
	/**
	 * ...
	 * @author pbordachar
	 */
	
	public class VideoConnector extends EventDispatcher implements IDisposable
	{
		private var _nc:NetConnection;
		private var _ns:NetStream;
		
		private var _server:String = null;
		private var _buffer:int;
		private var _paused:Boolean = false;
		private var _checked:Boolean = false;
		private var _agent:ILoaderAgent;
		
		private var _onStreamReady:Function;
		
		private var _flushed:Boolean = false;
		
		public function VideoConnector( parameters:VideoConnectorParameters ) 
		{	
			if( parameters != null ){
				_server = parameters.server;
				_buffer = parameters.buffered;
				_checked = parameters.checked;
				_agent = parameters.agent;
				_onStreamReady = parameters.onStreamReady;
			}
		}
		
		///////   N E T   C O N N E C T I O N
		
		public function init( ):void
		{
			NetConnection.defaultObjectEncoding = ObjectEncoding.AMF0;
			
			_nc = new NetConnection();
			_nc.client = this;
			_nc.objectEncoding = ObjectEncoding.AMF0;
			_nc.addEventListener( NetStatusEvent.NET_STATUS, _onNCStatus );
			_nc.connect( _server );
		}

		private function _onNCStatus( e:NetStatusEvent ):void
		{
			_nc.removeEventListener( NetStatusEvent.NET_STATUS, _onNCStatus );
			
			//trace( e.info.code );
			
			switch( e.info.code ) {
				
				case "NetConnection.Call.BadVersion" :
				case "NetConnection.Call.Failed" :
				case "NetConnection.Call.Prohibited" :
				case "NetConnection.Connect.AppShutdown" :
				case "NetConnection.Connect.InvalidApp" :
				case "NetConnection.Connect.Closed" :
				case "NetConnection.Connect.Failed" :
				case "NetConnection.Connect.Rejected" :
					break;
					
				case "NetConnection.Connect.Success" :
					_initStream();
					break;
					
				default :
					trace( e.info.code );
			}
		} 
		
		//////   N E T   S T R E A M
		
		private function _initStream():void 
		{
			_ns = new NetStream( _nc );
			_ns.checkPolicyFile = _checked;
			_ns.bufferTime = _buffer;
			
			_ns.client = new NetStreamClient();
			_ns.addEventListener( NetStatusEvent.NET_STATUS, _onNSStatus );

			if ( _onStreamReady != null ) _onStreamReady();
		}
		
		private function _onNSStatus( e:NetStatusEvent ):void
		{ 
			//trace( e.info.code );
			
			switch( e.info.code ) {
				
				case "NetStream.Play.Start" : 
					if ( _agent ) _agent.addIndicator();
					break;
					
				case "NetStream.Play.Stop" :
					if( _agent ) _agent.removeIndicator();
					_checkComplete();
					break;
					
				/// B U F F E R 
					
				case "NetStream.Buffer.Empty" :
					if( !_paused ){
						if( _agent ) _agent.addIndicator();
					} else {
						if( _agent ) _agent.removeIndicator();
					}
					break;

				case "NetStream.Buffer.Full" :
					_flushed = false;
					if( _agent ) _agent.removeIndicator();
					break;
				
				case "NetStream.Buffer.Flush" :
					_flushed = true;
					break;
					
				/// S E E K	
				
				case "NetStream.Seek.Failed" :
				case "NetStream.Seek.Notify" :
				case "NetStream.Seek.Complete" :
					break;
				
				default :
				
					if( e.info.level == "error" ){
						trace("Stream Not Found");
					}
			}
		}
		
		private function _checkComplete():void
		{
			if ( _flushed && _ns.client.duree > 0 && ( _ns.client.duree - _ns.time) < .1 ) 
			{
				dispatchEvent( new MediaEvent( MediaEvent.PLAY_COMPLETE ) );
			}
		}
		
		// - - -
		
		private function _closeConnection():void
		{
			if ( _ns != null ) {
				_ns.removeEventListener( NetStatusEvent.NET_STATUS, _onNSStatus );
				_ns.pause();
				_ns.close();
			}
			if( _nc != null ){
				_nc.close();
			}
		}

		public function dispose():void
		{
			_closeConnection();
			
			_ns = null;
			_nc = null;
			
			_agent = null;
		}
		
		// - - - -
		
		public function get netStream():NetStream 
		{
			return _ns;
		}
		
		
	}

}